#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sqlite3.h>

typedef struct student student;
struct student {
    int id;
    char name[255];
    char tel[12];
    student *next;
};

student *create_node(int id, char *name, char *tel) {
    student *node = (student *) malloc(sizeof(student));
    node->id = id;
    strcpy(node->name, name);
    strcpy(node->tel, tel);
    node->next = NULL;
    printf("create node success\n");
    return node;
}


void insert_node(student *pStudent, student *head, int position) {
    student *pre_head;
    printf("position:%d\n", position);
    for (int i = 0; i < position; ++i) {
        pre_head = head;
        head = head->next;
    }
    pStudent->next = head;
    pre_head->next = pStudent;
}

int select_position(student *pStudent, student *head) {
    int i = 0;

    while (1) {
        if (head == NULL) {
            break;
        }
        if (head->id > pStudent->id) {
            break;
        }
        i++;

        head = head->next;
    }
    printf("select_position success\n");
    return i;
}

void addinfo(student *head) {
    int id;
    char name[255];
    char tel[12];
    student *node;
    printf("please enter id\n");
    scanf("%d", &id);
    getchar();
    printf("please enter name\n");
    scanf("%s", name);
    getchar();
    printf("please enter telephone\n");
    scanf("%s", tel);
    getchar();

    student *temp = head;
    while (1) {
        if (temp == NULL) {
            break;
        }
        if (temp->id == id) {
            printf("primary key dup please reEnter\n");
            return;
        }
        temp = temp->next;
    }
    node = create_node(id, name, tel);
    int position;
    position = select_position(node, head);
    insert_node(node, head, position);
}

void disinfo(student *head) {
    printf("%16s%16s%16s\n", "id", "name", "telephone");
    if (head->next != NULL) {
        head = head->next;
        while (head != NULL) {
            printf("%16d%16s%16s\n", head->id, head->name, head->tel);
            head = head->next;
        }
    }

}

void menu() {
//    system("clear");

    printf("---------------------------------------------------------\n");
    printf("\t\t1.add   2.dis\n");
    printf("\t\t3.fid   4.mdf\n");
    printf("\t\t5.del   6.exit\n");
    printf("---------------------------------------------------------\n");
}

void findinfo(student *head, int find_id) {
    head = head->next;
    while (1) {
        if (head == NULL) {
            printf("sorry there is no student ID is:%d\n", find_id);
            break;
        }
        if (head->id == find_id) {
            printf("%16d%16s%16s\n", head->id, head->name, head->tel);
            break;
        }
        head = head->next;
    }

}

void deleteinfo(student *head, int find_id) {
    student *pre_head = head;
    head = head->next;
    while (1) {
        if (head == NULL) {
            printf("sorry there is no student ID is:%d\n", find_id);
            break;
        }
        if (head->id == find_id) {
            pre_head->next = head->next;
            free(head);
            printf("delete student info success\n");

            sqlite3 *db;
            const char filename[] = "sqlite.db";
            if (sqlite3_open(filename, &db) != SQLITE_OK) {
                printf("DELETE SAVE DESK WRONGING!!!\n");
                return;
            }
            char sql_delete[255];
            sprintf(sql_delete, "delete from student where id=%d;", find_id);
            if (sqlite3_exec(db, sql_delete, NULL, NULL, NULL) != SQLITE_OK) {
                printf("DELETE SAVE DESK WRONGING!!!\n");

            } else {
                printf("DELETE SAVE DESK SUCCESS\n");
            }
            break;
        }
        pre_head = head;
        head = head->next;
    }
}

void modify_server(student *head) {

    int id;
    char name[255];
    char tel[12];
    student *node;
    printf("please enter MODIFY id\n");
    scanf("%d", &id);
    getchar();
    printf("please enter MODIFY name\n");
    scanf("%s", name);
    getchar();
    printf("please enter MODIFY telephone\n");
    scanf("%s", tel);
    getchar();


    student *pre_head = head;
    head = head->next;
    while (1) {
        if (head == NULL) {
            printf("sorry there is no student ID to MODIFY\n");
            break;
        }
        if (head->id == id) {
            node = create_node(id, name, tel);
            node->next = head->next;
            pre_head->next = node;
            free(head);
            printf("MODIFY student info success\n");

            sqlite3 *db;
            const char filename[] = "sqlite.db";
            if (sqlite3_open(filename, &db) != SQLITE_OK) {
                printf("MODIFY SERVER SAVE DESK WRONGING!!!\n");
                return;
            }
            char sql_update[255];
            sprintf(sql_update, "update student set name='%s',telephone='%s' where id=%d;", name, tel, id);
            if (sqlite3_exec(db, sql_update, NULL, NULL, NULL) != SQLITE_OK) {
                printf("MODIFY SERVER SAVE DESK WRONGING!!!\n");
            } else {
                printf("MODIFY SAVE SUCCESS\n");
            }
            sqlite3_close(db);
            break;
        }
        pre_head = head;
        head = head->next;
    }


}

static int callback(void *Used, int argc, char **argv, char **azColName) {
    student *head = (student *) Used;
    student *node;
    node = create_node(atoi(argv[0]), argv[1], argv[2]);
    int position;
    position = select_position(node, head);
    insert_node(node, head, position);
    return 0;
}

void exit_sys(student *head) {
    sqlite3 *db;
    const char filename[] = "sqlite.db";
    if (sqlite3_open(filename, &db) != SQLITE_OK) {
        printf("SAVE DB FAIL WRONGING!!!\n");
        printf("CAN　NOT END PROCESS\n");
        return;
    }
    char sql[] = "create table if not exists student(id int primary key,name varchar(255),telephone varchar(255));";
    if (sqlite3_exec(db, sql, NULL, NULL, NULL) != SQLITE_OK) {
        printf("EXEC CREATE TABLE FAIL WRONG!!!\n");
        return;
    }
    char insert_sql[512];


    head = head->next;
    while (head) {
        memset(insert_sql, 0, sizeof(insert_sql));
        sprintf(insert_sql, "insert into student(id,name,telephone)values(%d,'%s','%s');", head->id, head->name,
                head->tel);
        if (sqlite3_exec(db, insert_sql, NULL, NULL, NULL) != SQLITE_OK) {
//            printf("EXEC INSERT DATA FAIL WRONG!!!\n");
        }
        head = head->next;
    }
    sqlite3_close(db);
    exit(0);


}

void init_head(student *head) {
    sqlite3 *db;
    const char filename[] = "sqlite.db";
    if (sqlite3_open(filename, &db) != SQLITE_OK) {
        printf(" INIT DB FAIL WRONGING!!!\n");
        return;
    }
    char sql[] = "create table if not exists student(id int primary key,name varchar(255),telephone varchar(255));";
    if (sqlite3_exec(db, sql, NULL, NULL, NULL) != SQLITE_OK) {
        printf("EXEC CREATE TABLE FAIL WRONG!!!\n");
        return;
    }
    char sql_select[] = "select * from student;";
    if ((sqlite3_exec(db, sql_select, callback, head, NULL)) != SQLITE_OK) {
//
    }
    sqlite3_close(db);
}

int main() {
    char choose;
    int find_id;
    student *head;
    head = create_node(-1, "@head", "-1");
    init_head(head);
    while (1) {
        menu();
        printf("please enter choose :\n");
        scanf("%c", &choose);
        getchar();
        switch (choose) {
            case '1':
                addinfo(head);
                break;
            case '2':
                disinfo(head);
                break;
            case '3':
                printf("please enter student ID\n");
                scanf("%d", &find_id);
                getchar();
                findinfo(head, find_id);
                break;
            case '4':
                modify_server(head);
                break;
            case '5':
                printf("please enter delete student ID\n");
                scanf("%d", &find_id);
                getchar();
                deleteinfo(head, find_id);
                break;
            case '6':
                exit_sys(head);
            default:;
        }

    }

    return 0;
}
